﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using FasterWPF;

namespace FasterWPF
{
    public class CanvasComposite : IComposite
    {
        public bool IsGrid()
        {
            return false;
        }

        public void RemoveFromChain(Border bdr) //unhook all the children so they may be re-added later, if desired
        {
            GetContainer<Canvas>(bdr).Children.Clear();
        }

        public C GetContainer<C>(Border bdr)
            where C: FrameworkElement
        {
           return ((C)(((ContentControl)(bdr.Child)).Content));
        }

        public C GetContainerFromChildContentControl<C>(ContentControl chain) where C : FrameworkElement
        {
           return ((C)(chain.Content));
        }

        public T GetParent<T>(ContentControl sender)
              where T : FrameworkElement
        {
            return (T)((ContentControl)sender).GetParentFromContentControlOfComposite<T>();
        }

        public Panel AddChild<T>(T source, System.Windows.Controls.ContentControl chain, int row, int col, System.Windows.FrameworkElement child)
               where T : FrameworkElement
        {
            Canvas g = ((Canvas)(chain.Content));
            g.Children.Add(child);
            Canvas.SetTop(child, row);
            Canvas.SetLeft(child, col);
            return (Panel)g;
        }

        public void AddCompositeToContentControl<T>(T chain, ContentControl contentControl, object settings)
            where T: FrameworkElement
        {
            Canvas g = new Canvas();

            CanvasSettings gs = null;

            if (settings != null)
            {
                gs = (settings as CanvasSettings);
            }
            else
            {
                if (SettingsManager.ContainsSetting<T>(chain, "CanvasSettings"))
                {
                    gs = SettingsManager.GetSetting<T, CanvasSettings>(chain, "CanvasSettings");
                }
                else
                {
                    //no default settings
                    throw new Exception("Canvas Settings must be defined on Parent T.");
                }
            }
            applyCanvasSettings(gs, g);

            contentControl.Content = g;      
        }

        private static Canvas applyCanvasSettings(CanvasSettings canvasSet, Canvas g)
        {
            g.Height = canvasSet.Height;
            g.Width = canvasSet.Width;

            if (canvasSet.BackgroundColor != null)
            {
                ChangeBackgroundColor(g, canvasSet.BackgroundColor);
            }

            if (canvasSet.MouseOverColor != null)
            {
                SetMouseOverColorOnCanvas(g, canvasSet.MouseOverColor);
            }

            return g;
        }

        //Due to order of precedence issues, only set Background Color via styles 
        //(so that we can apply MouseOverColor triggers)
        private static void ChangeBackgroundColor(Canvas button, Brush newColor)
        {
            if (button != null)
            {
                Style style = new Style(typeof(Canvas), button.Style);

                Setter setter = new Setter();
                setter.Property = Canvas.BackgroundProperty;
                setter.Value = newColor;
                style.Setters.Add(setter);

                button.Style = style;
            }
        }

        private static void SetMouseOverColorOnCanvas(Canvas parentBorder, Brush brush)
        {
            Style style = new Style(typeof(Canvas), parentBorder.Style);
            Trigger t = new Trigger();
            t.Property = Canvas.IsMouseOverProperty;
            t.Value = true;
            Setter setter = new Setter();
            setter.Property = Canvas.BackgroundProperty;
            setter.Value = brush;
            t.Setters.Add(setter);

            style.Triggers.Add(t); // Important: add a trigger before applying style
            parentBorder.Style = style;
        }

        public T GetParentFromChild<T>(FrameworkElement childElement) where T : FrameworkElement
        {
            return (T)((ContentControl)((Canvas)((FrameworkElement)childElement.Parent)).Parent).GetParentFromContentControlOfComposite<T>();
        }

        public System.Windows.Controls.Border GetBorder<T>(System.Windows.FrameworkElement childElement)
        {
            return (Border)((Canvas)((FrameworkElement)childElement).Parent).Parent.Cast<ContentControl>().Parent;
        }
        
        public K Get<K, T>(System.Windows.Controls.ContentControl chain, int row, int column)
                where K : UIElement
                where T : FrameworkElement
        {
            K label = default(K);

            foreach(UIElement j in ((Canvas)(chain.Content)).Children)
            {
                if (Canvas.GetTop(j) == row && Canvas.GetLeft(j) == column)
                {
                    label = (K)j;
                }
            }

            return label;
        }

        public UIElementCollection GetChildren(object container)
        {
            return (container as Canvas).Children;
        }
    }
}
